Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / backend / test_landlock_integration_surfaces.py

Displaying Raw • Download


tests/backend/test_landlock_integration_surfaces.py 37edfa4cfe5aa2f6ebb7e4aeac2e2c67ad181a52 (37edfa4c) Text, 12.58 KB

T8b949e# SPDX-License-Identifier: 0BSD

T8b949e"""Landlock regression probes for subprocess and user-local tool surfaces."""

Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations

Tff7b72import T7ee787os
Tff7b72import T7ee787shutil
Tff7b72import T7ee787tempfile

Tff7b72import T7ee787pytest

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backend Tff7b72import Te6edf3landlock_sandbox Tff7b72as Te6edf3ll
Tff7b72from T7ee787testsT7ee787.T7ee787backendT7ee787.T7ee787landlock_integration_support Tff7b72import Tb4b4b4(
Te6edf3assert_probe_okTb4b4b4,
Te6edf3requires_landlock_integrationTb4b4b4,
Te6edf3run_python_under_landlockTb4b4b4,
Te6edf3skip_if_landlock_not_appliedTb4b4b4,
Tb4b4b4)


Tff7b72def Td2a8fftest_collect_user_local_cli_roots_expected_layoutTb4b4b4(Te6edf3tmp_pathTb4b4b4, Te6edf3monkeypatchTb4b4b4)Tb4b4b4:
Te6edf3home Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffhomeTa5d6ff"
Te6edf3local_bin Tff7b72= Te6edf3home Tff7b72/ Ta5d6ff"Ta5d6ff.localTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffbinTa5d6ff"
Te6edf3pipx Tff7b72= Te6edf3home Tff7b72/ Ta5d6ff"Ta5d6ff.localTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffshareTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffpipxTa5d6ff"
Te6edf3argos Tff7b72= Te6edf3home Tff7b72/ Ta5d6ff"Ta5d6ff.localTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffshareTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffargos-translateTa5d6ff"
Te6edf3local_binTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3pipxTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3argosTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3monkeypatchTff7b72.Td2a8ffsetenvTb4b4b4(Ta5d6ff"Ta5d6ffHOMETa5d6ff"Tb4b4b4, Tffa657strTb4b4b4(Te6edf3homeTb4b4b4)Tb4b4b4)

Te6edf3roots Tff7b72= Tffa657setTb4b4b4(Te6edf3llTff7b72.Td2a8ff_collect_user_local_cli_rootsTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72assert Tffa657strTb4b4b4(Te6edf3local_binTb4b4b4) Tff7b72in Te6edf3roots
Tff7b72assert Tffa657strTb4b4b4(Te6edf3pipxTb4b4b4) Tff7b72in Te6edf3roots
Tff7b72assert Tffa657strTb4b4b4(Te6edf3argosTb4b4b4) Tff7b72in Te6edf3roots


Tff7b72def Td2a8fftest_collect_rw_roots_includes_argos_share_when_presentTb4b4b4(Te6edf3tmp_pathTb4b4b4, Te6edf3monkeypatchTb4b4b4)Tb4b4b4:
Te6edf3home Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffhomeTa5d6ff"
Te6edf3argos Tff7b72= Te6edf3home Tff7b72/ Ta5d6ff"Ta5d6ff.localTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffshareTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffargos-translateTa5d6ff"
Te6edf3argosTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3monkeypatchTff7b72.Td2a8ffsetenvTb4b4b4(Ta5d6ff"Ta5d6ffHOMETa5d6ff"Tb4b4b4, Tffa657strTb4b4b4(Te6edf3homeTb4b4b4)Tb4b4b4)

Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3rw Tff7b72= Te6edf3llTff7b72.Td2a8ff_collect_rw_rootsTb4b4b4(Tffa657strTb4b4b4(Te6edf3storageTb4b4b4)Tb4b4b4, Tff7b72NoneTb4b4b4, Tffa657strTb4b4b4(Te6edf3storageTb4b4b4)Tb4b4b4)
Tff7b72assert Tffa657strTb4b4b4(Te6edf3argosTb4b4b4) Tff7b72in Te6edf3rw


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_denies_write_directly_under_homeTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
T8b949e"""HOME is not an RW root; only storage, temp, and explicit shares are."""
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
T8b949e"""
import os
import sys

path = os.path.join(
os.path.expanduser("~"),
".meshchatx_landlock_write_probe",
)
try:
with open(path, "w", encoding="utf-8") as handle:
handle.write("x")
except PermissionError:
print("OK")
sys.exit(0)
try:
os.remove(path)
except OSError:
pass
print("WRITE_SHOULD_HAVE_FAILED")
sys.exit(3)
"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_allows_storage_and_temp_writesTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff import os
Ta5d6ff import sys
Ta5d6ff import tempfile

Ta5d6ff storage = Tffd700{Tffa657strTb4b4b4(Te6edf3storageTb4b4b4)Tffd700!r}
Ta5d6ff path = os.path.join(storage, Ta5d6ff"Ta5d6ffrw-check.txtTa5d6ff"Ta5d6ff)
Ta5d6ff with open(path, Ta5d6ff"Ta5d6ffwTa5d6ff"Ta5d6ff, encoding=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Ta5d6ff) as handle:
Ta5d6ff handle.write(Ta5d6ff"Ta5d6ffstorageTa5d6ff"Ta5d6ff)
Ta5d6ff with tempfile.NamedTemporaryFile(
Ta5d6ff mode=Ta5d6ff"Ta5d6ffwTa5d6ff"Ta5d6ff,
Ta5d6ff encoding=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Ta5d6ff,
Ta5d6ff delete=True,
Ta5d6ff ) as tmp:
Ta5d6ff tmp.write(Ta5d6ff"Ta5d6fftempTa5d6ff"Ta5d6ff)
Ta5d6ff print(Ta5d6ff"Ta5d6ffOKTa5d6ff"Ta5d6ff)
Ta5d6ff sys.exit(0)
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_child_interpreter_spawnTb4b4b4(Tb4b4b4)Tb4b4b4:
T8b949e"""Same pattern as self_check.check_subprocess_spawn."""
Te6edf3storage Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkdtempTb4b4b4(Te6edf3prefixTff7b72=Ta5d6ff"Ta5d6ffmeshchat_ll_spawn_Ta5d6ff"Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
T8b949e"""
import subprocess
import sys

child = subprocess.run(
[sys.executable, "-c", "print('meshchatx-spawn-ok', flush=True)"],
capture_output=True,
text=True,
timeout=30,
check=False,
stdin=subprocess.DEVNULL,
)
if child.returncode != 0:
print("SPAWN_RC", child.returncode, child.stderr)
sys.exit(4)
if "meshchatx-spawn-ok" not in (child.stdout or ""):
print("SPAWN_BAD_OUT", child.stdout)
sys.exit(5)
print("OK")
sys.exit(0)
"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_self_check_subprocess_spawn_helperTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3storage Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkdtempTb4b4b4(Te6edf3prefixTff7b72=Ta5d6ff"Ta5d6ffmeshchat_ll_selfcheck_Ta5d6ff"Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
T8b949e"""
import sys
from meshchatx.src.backend.self_check import check_subprocess_spawn

out = check_subprocess_spawn()
if out.get("status") != "ok":
print("SELF_CHECK_FAIL", out.get("reason", ""))
sys.exit(3)
print("OK")
sys.exit(0)
"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_translator_handler_lists_argos_languagesTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
T8b949e"""
import sys
from meshchatx.src.backend.translator_handler import TranslatorHandler

handler = TranslatorHandler(translator_argos_enabled=True)
if not handler.has_argos:
print("SKIP_NO_ARGOS")
sys.exit(0)
resp = handler.get_translator_languages_response()
argos = [x for x in resp["languages"] if x.get("source") == "argos"]
if not argos:
print("EMPTY_ARGOS_LANGS has_lib", handler.has_argos_lib, "has_cli", handler.has_argos_cli)
sys.exit(4)
print("OK", len(argos))
sys.exit(0)
"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff120Tb4b4b4,
Tb4b4b4)
Te6edf3skip_if_landlock_not_appliedTb4b4b4(Te6edf3resultTb4b4b4)
Tff7b72if Ta5d6ff"Ta5d6ffSKIP_NO_ARGOSTa5d6ff" Tff7b72in Tb4b4b4(Te6edf3resultTff7b72.Td2a8ffstdout Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ffArgos Translate not installed on this hostTa5d6ff"Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_argospm_list_when_installedTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3shutilTff7b72.Td2a8ffwhichTb4b4b4(Ta5d6ff"Ta5d6ffargospmTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ffargospm not on PATHTa5d6ff"Tb4b4b4)
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
T8b949e"""
import subprocess
import sys

proc = subprocess.run(
["argospm", "list"],
capture_output=True,
text=True,
timeout=30,
check=False,
)
if proc.returncode != 0:
print("ARGOSPM_FAIL", proc.stderr or proc.stdout)
sys.exit(3)
if not (proc.stdout or "").strip():
print("ARGOSPM_EMPTY")
sys.exit(4)
print("OK")
sys.exit(0)
"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_argos_translate_cli_when_installedTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3executable Tff7b72= Te6edf3shutilTff7b72.Td2a8ffwhichTb4b4b4(Ta5d6ff"Ta5d6ffargos-translateTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3executableTb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ffargos-translate not on PATHTa5d6ff"Tb4b4b4)
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff import subprocess
Ta5d6ff import sys

Ta5d6ff proc = subprocess.run(
Ta5d6ff [Tffd700{Te6edf3executableTffd700!r}Ta5d6ff, Ta5d6ff"Ta5d6ff--from-langTa5d6ff"Ta5d6ff, Ta5d6ff"Ta5d6ffenTa5d6ff"Ta5d6ff, Ta5d6ff"Ta5d6ff--to-langTa5d6ff"Ta5d6ff, Ta5d6ff"Ta5d6ffruTa5d6ff"Ta5d6ff, Ta5d6ff"Ta5d6ffhelloTa5d6ff"Ta5d6ff],
Ta5d6ff capture_output=True,
Ta5d6ff text=True,
Ta5d6ff timeout=120,
Ta5d6ff check=False,
Ta5d6ff )
Ta5d6ff if proc.returncode != 0:
Ta5d6ff print(Ta5d6ff"Ta5d6ffTRANSLATE_FAILTa5d6ff"Ta5d6ff, proc.stderr or proc.stdout)
Ta5d6ff sys.exit(3)
Ta5d6ff if not (proc.stdout or Ta5d6ff"Ta5d6ff"Ta5d6ff).strip():
Ta5d6ff print(Ta5d6ff"Ta5d6ffTRANSLATE_EMPTYTa5d6ff"Ta5d6ff)
Ta5d6ff sys.exit(4)
Ta5d6ff print(Ta5d6ff"Ta5d6ffOKTa5d6ff"Ta5d6ff)
Ta5d6ff sys.exit(0)
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff180Tb4b4b4,
Tb4b4b4)
Te6edf3skip_if_landlock_not_appliedTb4b4b4(Te6edf3resultTb4b4b4)
Tff7b72if Te6edf3resultTff7b72.Td2a8ffreturncode Tff7b72!= T79c0ff0 Tff7b72and Ta5d6ff"Ta5d6fftranslate-en_ruTa5d6ff" Tff7b72in Tb4b4b4(
Te6edf3resultTff7b72.Td2a8ffstdout Tff7b72or Te6edf3resultTff7b72.Td2a8ffstderr Tff7b72or Ta5d6ff"Ta5d6ff"
Tb4b4b4)Tb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6fftranslate-en_ru package not installedTa5d6ff"Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_argos_share_allows_stanza_style_temp_dirTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3home Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(Ta5d6ff"Ta5d6ff~Ta5d6ff"Tb4b4b4)
Te6edf3argos_share Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3homeTb4b4b4, Ta5d6ff"Ta5d6ff.localTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffshareTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffargos-translateTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3argos_shareTb4b4b4)Tb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ffArgos data directory not presentTa5d6ff"Tb4b4b4)
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff import os
Ta5d6ff import sys
Ta5d6ff import tempfile

Ta5d6ff base = Tffd700{Te6edf3argos_shareTffd700!r}
Ta5d6ff with tempfile.TemporaryDirectory(dir=base) as td:
Ta5d6ff path = os.path.join(td, Ta5d6ff"Ta5d6ffprobe.txtTa5d6ff"Ta5d6ff)
Ta5d6ff with open(path, Ta5d6ff"Ta5d6ffwTa5d6ff"Ta5d6ff, encoding=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Ta5d6ff) as handle:
Ta5d6ff handle.write(Ta5d6ff"Ta5d6ffokTa5d6ff"Ta5d6ff)
Ta5d6ff print(Ta5d6ff"Ta5d6ffOKTa5d6ff"Ta5d6ff)
Ta5d6ff sys.exit(0)
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_user_local_bin_script_executableTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3local_bin Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(Ta5d6ff"Ta5d6ff~Ta5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff.localTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffbinTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3local_binTb4b4b4)Tb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ff~/.local/bin not presentTa5d6ff"Tb4b4b4)
T8b949e# Pipx-style CLIs only. git-remote-rns imports RNS at startup and is not a
T8b949e# generic --help smoke target for Landlock execute permission.
Te6edf3preferred Tff7b72= Tb4b4b4(
Tb4b4b4(Ta5d6ff"Ta5d6ffargospmTa5d6ff"Tb4b4b4, Tb4b4b4[Ta5d6ff"Ta5d6ff--helpTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4(Ta5d6ff"Ta5d6ffargos-translateTa5d6ff"Tb4b4b4, Tb4b4b4[Ta5d6ff"Ta5d6ff--helpTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4(Ta5d6ff"Ta5d6ffargostranslateTa5d6ff"Tb4b4b4, Tb4b4b4[Ta5d6ff"Ta5d6ff--helpTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3cmd Tff7b72= Tff7b72None
Te6edf3cmd_argv Tff7b72= Tff7b72None
Tff7b72for Te6edf3nameTb4b4b4, Te6edf3extra_argv Tff7b72in Te6edf3preferredTb4b4b4:
Te6edf3path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3local_binTb4b4b4, Te6edf3nameTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3pathTb4b4b4) Tff7b72and Te6edf3osTff7b72.Td2a8ffaccessTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3osTff7b72.Td2a8ffX_OKTb4b4b4)Tb4b4b4:
Te6edf3cmd Tff7b72= Te6edf3path
Te6edf3cmd_argv Tff7b72= Tb4b4b4[Te6edf3pathTb4b4b4, Tff7b72*Te6edf3extra_argvTb4b4b4]
Tff7b72break
Tff7b72if Te6edf3cmd Tff7b72is Tff7b72None Tff7b72or Te6edf3cmd_argv Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ffno known pipx-style CLI in ~/.local/binTa5d6ff"Tb4b4b4)
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff import subprocess
Ta5d6ff import sys

Ta5d6ff proc = subprocess.run(
Ta5d6ff Tffd700{Te6edf3cmd_argvTffd700!r}Ta5d6ff,
Ta5d6ff capture_output=True,
Ta5d6ff text=True,
Ta5d6ff timeout=10,
Ta5d6ff check=False,
Ta5d6ff )
Ta5d6ff if proc.returncode != 0:
Ta5d6ff print(Ta5d6ff"Ta5d6ffEXEC_FAILTa5d6ff"Ta5d6ff, proc.stderr)
Ta5d6ff sys.exit(3)
Ta5d6ff print(Ta5d6ff"Ta5d6ffOKTa5d6ff"Ta5d6ff)
Ta5d6ff sys.exit(0)
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_git_version_when_git_on_pathTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3git Tff7b72= Te6edf3shutilTff7b72.Td2a8ffwhichTb4b4b4(Ta5d6ff"Ta5d6ffgitTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3gitTb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ffgit not on PATHTa5d6ff"Tb4b4b4)
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff import subprocess
Ta5d6ff import sys

Ta5d6ff proc = subprocess.run(
Ta5d6ff [Tffd700{Te6edf3gitTffd700!r}Ta5d6ff, Ta5d6ff"Ta5d6ff--versionTa5d6ff"Ta5d6ff],
Ta5d6ff capture_output=True,
Ta5d6ff text=True,
Ta5d6ff timeout=15,
Ta5d6ff check=False,
Ta5d6ff )
Ta5d6ff if proc.returncode != 0:
Ta5d6ff print(Ta5d6ff"Ta5d6ffGIT_FAILTa5d6ff"Ta5d6ff, proc.stderr)
Ta5d6ff sys.exit(3)
Ta5d6ff if Ta5d6ff"Ta5d6ffgit versionTa5d6ff"Ta5d6ff not in (proc.stdout or Ta5d6ff"Ta5d6ff"Ta5d6ff):
Ta5d6ff print(Ta5d6ff"Ta5d6ffGIT_BAD_OUTTa5d6ff"Ta5d6ff, proc.stdout)
Ta5d6ff sys.exit(4)
Ta5d6ff print(Ta5d6ff"Ta5d6ffOKTa5d6ff"Ta5d6ff)
Ta5d6ff sys.exit(0)
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@requires_landlock_integration
Tff7b72def Td2a8fftest_landlock_rnsh_module_spawn_when_installedTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72import T7ee787importlibT7ee787.T7ee787util

Tff7b72if Te6edf3importlibTff7b72.Td2a8ffutilTff7b72.Td2a8fffind_specTb4b4b4(Ta5d6ff"Ta5d6ffRNS.Utilities.rnsh.rnshTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ffrnsh module not installedTa5d6ff"Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149ImportErrorTb4b4b4, Tf85149ValueErrorTb4b4b4, Tf85149AttributeErrorTb4b4b4)Tb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6ff"Ta5d6ffrnsh module not installedTa5d6ff"Tb4b4b4)

Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffstorageTa5d6ff"
Te6edf3rns_dir Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffrnsTa5d6ff"
Te6edf3rns_dirTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3storageTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3run_python_under_landlockTb4b4b4(
T8b949e"""
import subprocess
import sys

proc = subprocess.run(
[sys.executable, "-m", "RNS.Utilities.rnsh.rnsh", "--help"],
capture_output=True,
text=True,
timeout=20,
check=False,
)
out = (proc.stdout or "") + (proc.stderr or "")
if proc.returncode not in (0, 1, 2) and "rnsh" not in out.lower():
print("RNSH_HELP_FAIL", proc.returncode, out[-500:])
sys.exit(3)
print("OK")
sys.exit(0)
"""Tb4b4b4,
Te6edf3storageTff7b72=Te6edf3storageTb4b4b4,
Te6edf3reticulum_config_dirTff7b72=Te6edf3rns_dirTb4b4b4,
Tb4b4b4)
Te6edf3assert_probe_okTb4b4b4(Te6edf3resultTb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffparametrizeTb4b4b4(
Tb4b4b4(Ta5d6ff"Ta5d6ffpath_nameTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcollectorTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4[
Tb4b4b4(Ta5d6ff"Ta5d6fflocal_binTa5d6ff"Tb4b4b4, Tff7b72lambda Te6edf3homeTb4b4b4: Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3homeTb4b4b4, Ta5d6ff"Ta5d6ff.localTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffbinTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4(Ta5d6ff"Ta5d6ffpipxTa5d6ff"Tb4b4b4, Tff7b72lambda Te6edf3homeTb4b4b4: Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3homeTb4b4b4, Ta5d6ff"Ta5d6ff.localTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffshareTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpipxTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4(
Ta5d6ff"Ta5d6ffargos_shareTa5d6ff"Tb4b4b4,
Tff7b72lambda Te6edf3homeTb4b4b4: Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3homeTb4b4b4, Ta5d6ff"Ta5d6ff.localTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffshareTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffargos-translateTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8fftest_read_roots_cover_user_local_paths_when_presentTb4b4b4(Te6edf3path_nameTb4b4b4, Te6edf3collectorTb4b4b4)Tb4b4b4:
Te6edf3home Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(Ta5d6ff"Ta5d6ff~Ta5d6ff"Tb4b4b4)
Te6edf3target Tff7b72= Te6edf3collectorTb4b4b4(Te6edf3homeTb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3targetTb4b4b4)Tb4b4b4:
Te6edf3pytestTff7b72.Td2a8ffskipTb4b4b4(Ta5d6fffTa5d6ff"Tffd700{Te6edf3path_nameTffd700}Ta5d6ff not present on this hostTa5d6ff"Tb4b4b4)
Te6edf3roots Tff7b72= Te6edf3llTff7b72.Td2a8ff_collect_read_rootsTb4b4b4(Tb4b4b4)
Tff7b72assert Tffa657anyTb4b4b4(
Te6edf3target Tff7b72== Te6edf3root Tff7b72or Te6edf3targetTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3rootTff7b72.Td2a8ffrstripTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4) Tff7b72for Te6edf3root Tff7b72in Te6edf3roots
Tb4b4b4)Tb4b4b4, Ta5d6fffTa5d6ff"Tffd700{Te6edf3targetTffd700!r}Ta5d6ff not covered by landlock read roots (Tffd700{Te6edf3path_nameTffd700}Ta5d6ff)Ta5d6ff"


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────